﻿#region Copyright and License Notice
// Copyright (C)2010-2016 - Rob Levine and other contributors
// http://configgen.codeplex.com
// 
// This file is part of ConfigGen.
// 
// ConfigGen is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// ConfigGen is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License and 
// the GNU Lesser General Public License along with ConfigGen.  
// If not, see <http://www.gnu.org/licenses/>
#endregion

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace ConfigGen.Core
{
    /// <summary>
    /// Contains the results of a single file generation.
    /// </summary>
    public class SingleFileGenerationResults
    {
        /// <summary>
        /// Gets or sets a "count" dictionary for unrecognised tokens.
        /// </summary>
        /// <remarks>
        /// <para>An unrecognised token is one which appears in the template, but not in the settings file.</para>
        /// <para>A "count" dictionary is one with a string key, and an integer value which acts as a counter for the key.</para>
        /// </remarks>
        public IDictionary<string, int> UnrecognisedTokenCounts { get; set; }

        /// <summary>
        /// Gets or sets a "count" dictionary for tokens use.
        /// </summary>
        /// <remarks>
        /// <para>The token use count is incremented once for each token each time it is encountered in the template.</para>
        /// <para>A "count" dictionary is one with a string key, and an integer value which acts as a counter for the key.</para>
        /// </remarks>
        public IDictionary<string, int> TokenUseCounts { get; set; }

        /// <summary>
        /// Gets or sets the MD5 hash of the old configuration file, prior to it being overwritten with the new generated file.
        /// </summary>
        public byte[] OldFileMd5Hash { get; set; }

        /// <summary>
        /// Gets or sets the MD5 hash of the new configuration file as it is written to the file. This will be populated even if the "inhibit-write" option was enabled.
        /// </summary>
        public byte[] NewFileMd5Hash { get; set; }

        /// <summary>
        /// Gets or sets a <see cref="FileInfo"/> instance representing the generated configuration file.
        /// </summary>
        public FileInfo GeneratedFile { get; set; }

        /// <summary>
        /// Gets or sets the machine name to which the generated config file pertians.
        /// </summary>
        public string MachineName { get; set; }

        /// <summary>
        /// Gets a flag indicating if any warnings were encountered during generation.
        /// </summary>
        /// <remarks>
        /// <para>An warning occurs when each of the following conditions are encountered:
        /// <ul>
        /// <li>A token is encountered in the template file that was not specified in the settings file. This corresponds to a single count in <see cref="UnrecognisedTokenCounts"/></li>
        /// <li>A token is specified in the settings file but was not encountered in the template file. This corresponds to an entry with a zero count in <see cref="TokenUseCounts"/></li>
        /// </ul>
        /// </para>
        /// </remarks>
        /// <exception cref="InvalidOperationException">Thrown if either <see cref="UnrecognisedTokenCounts"/> or <see cref="InvalidOperationException"/> are null.</exception>
        public bool HasWarnings
        {
            get
            {
                if (UnrecognisedTokenCounts == null)
                {
                    throw new InvalidOperationException("Cannot call HasWarnings if UnrecognisedTokenCounts has not been set");
                }

                if (TokenUseCounts == null)
                {
                    throw new InvalidOperationException("Cannot call HasWarnings if TokenUseCounts has not been set");
                }

                return TokenUseCounts.Any(t => t.Value == 0)
                                   || UnrecognisedTokenCounts.Any(t => t.Value > 0);
            }
        }
    }
}
